#include "nyu_range.h"
#include "nyu_string.h"

NyuObject *nyu_range_proto = NULL;

static long nyu_range_proto_val = 0;
static NyuString *strval_each;

static NyuString *to_string(NyuObject *self);
static guint get_hash_code(NyuObject *self);
static gboolean equals(NyuObject *self, NyuObject *other);

long nyu_range_each(long argc, long *argv);

void nyu_range_initialize()
{
    if (nyu_range_proto)
        return;

    strval_each = nyu_string_new("each");

    nyu_range_proto = nyu_object_new();
    nyu_object_put_slot(nyu_range_proto, NYU_OBJECT(strval_each),
                        ((long)nyu_range_each | 1));

    nyu_range_proto_val = ((long)nyu_range_proto | 2);
}

void nyu_range_finalize()
{
    if (!nyu_range_proto)
        return;

    nyu_refcnt_unref(nyu_range_proto);
    nyu_range_proto = NULL;
    nyu_range_proto_val = 0;
    strval_each = NULL;
}

NyuRange *nyu_range_new(long from, long to, long step, int is_include_border)
{
    NyuRange *self;
    NyuObject *obj;

    self = nyu_refcnt_new(NyuRange);

    obj = NYU_OBJECT(self);

    NYU_OBJECT_INIT(obj, NYU_OBJECT_TYPE_RANGE, nyu_object_destroy);

    obj->to_string = to_string;
    obj->get_hash_code = get_hash_code;
    obj->equals = equals;

    nyu_refcnt_ref(nyu_range_proto);
    g_ptr_array_add(obj->slot_array, (gpointer)nyu_range_proto_val);
    g_hash_table_insert(obj->slots, nyu_refcnt_ref(strval_proto),
                        GINT_TO_POINTER(obj->slot_array->len));

    self->from = from;
    self->to = to;
    self->step = step;
    self->is_include_border = is_include_border;

    return self;
}

static NyuString *to_string(NyuObject *self)
{
    return nyu_string_new("TEST");
}

static guint get_hash_code(NyuObject *self)
{
    return (guint)((long)self);
}

static gboolean equals(NyuObject *self, NyuObject *other)
{
    return (self == other);
}
